package com.px.baolaiapi.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.px.common.api.CommonPage;
import com.px.common.api.CommonResult;
import com.px.common.constant.Constant;
import com.px.common.execption.Asserts;
import com.px.mbg.mapper.SaleShippingOrderMapper;
import com.px.mbg.model.*;
import com.px.baolaiapi.enums.ReceiptsTypeEnum;
import com.px.baolaiapi.page.SaleShippingOrderPage;
import com.px.baolaiapi.service.*;
import com.px.baolaiapi.util.JwtTokenUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 销售出货订单 服务实现类
 * </p>
 *
 * @author 品讯科技
 * @since 2022-05-13
 */
@Service
public class SaleShippingOrderServiceImpl extends ServiceImpl<SaleShippingOrderMapper, SaleShippingOrder> implements ISaleShippingOrderService {


    @Autowired
    ISaleOrderItemService saleOrderItemService;

    @Autowired
    ISaleShippingPlanService saleShippingPlanService;

    @Autowired
    ISaleShippingPlanItemService saleShippingPlanItemService;

    @Autowired
    ISaleShippingOrderService saleShippingOrderService;

    @Autowired
    ISaleShippingOrderItemService saleShippingOrderItemService;

    @Autowired
    ISequenceNumberService sequenceNumberService;

    @Autowired
    private IToDoListService toDoListService;
    @Autowired
    private IDocumentTypeService documentTypeService;
    @Autowired
    private ICommonBillService commonBillService;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;
    @Autowired
    private IInOutOfBillService inOutOfBillService;
    @Autowired
    private IBomService bomService;

    @Autowired
    private IUnitCnvRateService unitCnvRateService;
    @Autowired
    private IUnitService unitService;

    /**
     * 生成销售出货单
     *
     * @param ids
     * @return
     */
    @Override
    public CommonResult generateSaleShippingOrder(List<Long> ids) {
        for (Long id : ids) {
            SaleShippingPlan saleShippingPlan = saleShippingPlanService.getById(id);
            Preconditions.checkNotNull(saleShippingPlan);
            //生成销售出货单
            SaleShippingOrder bill = new SaleShippingOrder();
            BeanUtils.copyProperties(saleShippingPlan, bill);


            ReceiptsTypeEnum receiptsTypeEnum = ReceiptsTypeEnum.XSCH;
            bill.setReceiptsType(receiptsTypeEnum.getValue());
            String bnoType = bill.getBnoType();
            Preconditions.checkArgument(StringUtils.isNotBlank(bnoType), "单据类型必选");

            //单据类型同步后,获取位置变更
            DocumentType documentType = documentTypeService.getById(bnoType);
            if (ObjectUtil.isNull(documentType)) {
                Asserts.fail("未匹配到单据类型");
            }

            //String bnoNo = sequenceNumberService.createSequenceNumberRod(documentType.getCode(), "yyyy", 4, StrUtil.DASHED);
            String bnoNo = sequenceNumberService.createSequenceNumberRod("BLSM", "yyMM", 4, "");
            bill.setBnoNo(bnoNo);

            Users user = jwtTokenUtils.getUser();
            bill.setUserName(user.getUsername());
            bill.setUserAccount(user.getAccount());

            String batchNo = commonBillService.genBatchNo(documentType.getCode());
            bill.setCreateDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            bill.setFinishFlag(Constant.ORDER_FINISH_FLAG.UN_FINISH);
            bill.setPlanId(saleShippingPlan.getId());

            //生成销售单
            if (saleShippingOrderService.save(bill)) {

                List<SaleShippingPlanItem> saleShippingPlanItemList = saleShippingPlanItemService.list(new QueryWrapper<SaleShippingPlanItem>().lambda().eq(SaleShippingPlanItem::getShippingPlanId, saleShippingPlan.getId()));
                if (saleShippingPlanItemList.size() == 0) {
                    Asserts.fail("未匹配到销售出货单计划明细");
                }

                for (SaleShippingPlanItem saleShippingPlanItem : saleShippingPlanItemList) {
                    //生成销售明细单
                    SaleShippingOrderItem saleShippingOrderItem = new SaleShippingOrderItem();
                    BeanUtils.copyProperties(saleShippingPlanItem, saleShippingOrderItem);
                    saleShippingOrderItem.setShippingOrderId(bill.getId());
                    saleShippingOrderItem.setBatchNo(batchNo);
                    saleShippingOrderItemService.save(saleShippingOrderItem);
                }
                //改变销售备货计划状态
                saleShippingPlan.setStatus(Constant.SALE_SHIPPINGPLAN_STATUS.GENERATE);
                saleShippingPlanService.updateById(saleShippingPlan);
                // 添加待办任务记录
                toDoListService.addToDoList(bill.getId(), bill.getBnoNo(), receiptsTypeEnum, bill.getBnoType(), bill.getCustomerName());

                return CommonResult.success("");
            } else {
                Asserts.fail("生成销售单失败");
            }
        }
        return CommonResult.failed();
    }

    @Override
    public CommonPage querySaleShippingOrder(SaleShippingOrderPage page) {
        LambdaQueryWrapper<SaleShippingOrder> lambdaQueryWrapper = Wrappers.lambdaQuery(SaleShippingOrder.class);

        String bnoNo = page.getBnoNo();
        if (StringUtils.isNotEmpty(bnoNo)) {
            lambdaQueryWrapper.like(SaleShippingOrder::getBnoNo,bnoNo);
        }

        String custName = page.getCustomerName();
        if (StringUtils.isNotEmpty(custName)) {
            lambdaQueryWrapper.like(SaleShippingOrder::getCustomerName,custName);
        }

        String startDate = page.getStartDate();
        if (StringUtils.isNotEmpty(startDate)) {
            lambdaQueryWrapper.ge(SaleShippingOrder::getFcdDate, startDate);
        }

        String endDate = page.getEndDate();
        if (StringUtils.isNotEmpty(endDate)) {
            lambdaQueryWrapper.le(SaleShippingOrder::getFcdDate, endDate);
        }

        lambdaQueryWrapper.eq(page.getFinishFlag() != null && page.getFinishFlag() >= 0, SaleShippingOrder::getFinishFlag, page.getFinishFlag());
        lambdaQueryWrapper.orderByDesc(SaleShippingOrder::getCreatedTime);
        lambdaQueryWrapper.eq(SaleShippingOrder::getIsDelFlag,Constant.IS_ENABLED.ENABLE);

        CommonPage commonPage = CommonPage.restPage(this.page(new Page<>(page.getPageNum(), page.getPageRow()), lambdaQueryWrapper));
        List<SaleShippingOrder> list = commonPage.getList();

        List<JSONObject> jsonObjects = new ArrayList<>();
        for (SaleShippingOrder saleShippingOrder : list) {
            JSONObject jsonObject = billToJSONObject(saleShippingOrder);
            jsonObjects.add(jsonObject);
        }
        commonPage.setList(jsonObjects);
        return commonPage;
    }

    @Override
    public JSONObject querySaleShippingOrderItemById(Long id) {
        SaleShippingOrder saleShippingOrder = this.getById(id);
        if(ObjectUtil.isNotEmpty(saleShippingOrder)){
            JSONObject jsonObject = billToJSONObject(saleShippingOrder);

            List<JSONObject> dtoList = new ArrayList();
            List<SaleShippingOrderItem> list = saleShippingOrderItemService.list(new QueryWrapper<SaleShippingOrderItem>().lambda().eq(SaleShippingOrderItem::getShippingOrderId, id));
            if(CollectionUtils.isNotEmpty(list)){
                for (SaleShippingOrderItem detail : list) {
                    JSONObject dto = JSONUtil.parseObj(detail);
                    // 计划出货重量
                    String planWeight = "";
                    // 实发重量
                    String rWeight = "";

                    BigDecimal rNum = inOutOfBillService.getSumRealNumByBnoNoAndDetailId(saleShippingOrder.getBnoNo(), detail.getId());
                    dto.set("rNum", rNum);

                    Bom bom = bomService.queryBomByCode(detail.getMaterialCode());

                    //长度
                    dto.put("longt", bom.getLongt());
                    //长度单位
                    dto.put("lengthUnit", bom.getLengthUnit());
                    //宽度
                    dto.put("width", bom.getWidth());
                    //宽度单位
                    dto.put("widthUnit", bom.getWidthUnit());
                    //高度/厚度
                    dto.put("thickness", bom.getThickness());
                    //高度/厚度单位
                    dto.put("thicknessUnit", bom.getThicknessUnit());
                    //转化率
                    dto.put("rate", bom.getRatio());

//                    Map<String, Object> unitCN = bomService.getUnitCN(null, null, null, detail.getCvpUnit(), detail.getPcsUnit());
//                    dto.putAll(unitCN);

                    // 组织单位转换率数据
//                    UnitCnvRate unitCnvRate = unitCnvRateService.queryUnitCnvRateByBomCodeAndUnit(detail.getMaterialCode(),detail.getSaleUnit());
//                    if (ObjectUtil.isNotNull(unitCnvRate)) {
//                        planWeight = String.valueOf(unitCnvRate.getCnvRate().multiply(detail.getPlanNum()).setScale(2, BigDecimal.ROUND_UP));
//                        rWeight = String.valueOf(unitCnvRate.getCnvRate().multiply(rNum).setScale(2, BigDecimal.ROUND_UP));
//                        Unit unit = unitService.queryUnitByCode("",unitCnvRate.getTgtUnit());
//                        if (ObjectUtil.isNotNull(unit)) {
//                            weightUnit = unit.getUnitName();
//                        }
//                    }
                    planWeight = String.valueOf(bom.getRatio().multiply(detail.getPlanNum()).setScale(2, BigDecimal.ROUND_UP));
                    rWeight = String.valueOf(bom.getRatio().multiply(rNum).setScale(2, BigDecimal.ROUND_UP));
                    dto.set("rWeight", rWeight);
                    dto.set("planWeight", planWeight);
                    //成本单位
                    dto.set("weightUnit",bom.getWeightUnit());

                    dtoList.add(dto);
                }
            }
            jsonObject.set("saleShippingOrderItems", dtoList);
            return jsonObject;
        }
        return new JSONObject();
    }

    private JSONObject billToJSONObject(SaleShippingOrder bill){

        JSONObject dto = JSONUtil.parseObj(bill);
        //转换单据类型(U9)
        //单据类型同步后,获取位置变更
        DocumentType documentType = documentTypeService.getById(bill.getBnoType());
        if (ObjectUtil.isNull(documentType)) {
            Asserts.fail("未匹配到单据类型");
        }

        dto.set("bnoTypeName", documentType.getName());
        SaleShippingPlan saleShippingPlan = saleShippingPlanService.getById(bill.getPlanId());
        dto.set("planBnoNo", Optional.ofNullable(saleShippingPlan).map(SaleShippingPlan::getBnoNo).orElse(null));
        return dto;
    }



    
    public Object generateU9Data(String bnoNo, List<InOutOfBill> inOutOfBillList) {
        JSONObject jsonObject = new JSONObject();
        SaleShippingOrder saleShippingOrder = this.getOne(new QueryWrapper<SaleShippingOrder>().lambda().eq(SaleShippingOrder::getBnoNo,bnoNo).eq(SaleShippingOrder::getIsDelFlag,Constant.IS_ENABLED.ENABLE));
        jsonObject.set("organizationId",saleShippingOrder.getOrganizationId());
        jsonObject.set("organizationCode",saleShippingOrder.getOrganizationCode());
        jsonObject.set("organizationName",saleShippingOrder.getOrganizationName());
        jsonObject.set("bnoType",saleShippingOrder.getBnoType());
        jsonObject.set("bnoNo",saleShippingOrder.getBnoNo());
        jsonObject.set("customerCode",saleShippingOrder.getCustomerCode());
        jsonObject.set("customerName",saleShippingOrder.getCustomerName());
        jsonObject.set("createDate",saleShippingOrder.getCreateDate());
        jsonObject.set("fcdDate",saleShippingOrder.getFcdDate());
        jsonObject.set("bnoStatus",Constant.U9_BNO_STATUS.CLOSE);
        jsonObject.set("sourceCategory",saleShippingOrder.getSourceCategory());
        jsonObject.set("sourceDocuments",saleShippingOrder.getSourceDocuments());
        JSONArray jsonArray = new JSONArray();
        for (InOutOfBill inOutOfBill : inOutOfBillList) {
            SaleShippingOrderItem detail = saleShippingOrderItemService.getById(inOutOfBill.getBillDetailId());
            JSONObject jsonDetail = new JSONObject();
            jsonDetail.set("lineNo",detail.getLineNo());
            jsonDetail.set("saleOrderNo",detail.getSaleOrderId());
            jsonDetail.set("materialCode",detail.getMaterialCode());
            jsonDetail.set("materialName",detail.getMaterialName());
            jsonDetail.set("specification",detail.getSpecification());
            jsonDetail.set("pcsNum",inOutOfBill.getQty());
            jsonDetail.set("pcsUnit",inOutOfBill.getUnit());
            jsonDetail.set("saleNum",detail.getSaleNum());
            jsonDetail.set("saleUnitCode",detail.getSaleUnit());
            jsonDetail.set("cvpNum",detail.getCvpNum());
            jsonDetail.set("cvpUnit",detail.getCvpUnit());
            jsonDetail.set("storeAddress",inOutOfBill.getStgeCode());
            jsonDetail.set("storeBinCode",inOutOfBill.getStgeLocCode());
            jsonDetail.set("batchNo",detail.getBatchNo());
            jsonDetail.set("tLocation",detail.getDeliveryLocation());
            jsonDetail.set("remark",detail.getRemark());
            jsonDetail.set("longt",inOutOfBill.getLongt());
            jsonDetail.set("lengthUnit",inOutOfBill.getLengthUnit());
            jsonDetail.set("width",inOutOfBill.getWidth());
            jsonDetail.set("widthUnit",inOutOfBill.getWidthUnit());
            jsonDetail.set("thickness",inOutOfBill.getThickness());
            jsonDetail.set("thicknessUnit",inOutOfBill.getThicknessUnit());
            jsonArray.add(jsonDetail);
        }
        jsonObject.set("items",jsonArray);

        return jsonObject;
    }
}
